package com.ht.web360.PojServer.service;

import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.ht.web360.PojServer.dao.ObjRef;
import com.ht.web360.PojServer.mapper.ObjRefMapper;
import com.ht.web360.base.dto.PojInfo.dto.ObjRefDto;
import com.ht.web360.base.utils.RedisIdWorker;
import com.ht.web360.base.utils.exceptions.MessageException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
public class ObjRefService {

    @Lazy
    @Autowired
    ObjRefService _this;

    private final ObjRefMapper objRefMapper;
    @Autowired
    private RedisIdWorker redisIdWorker;

    public ObjRefService(ObjRefMapper objRefMapper) {
        this.objRefMapper = objRefMapper;
    }

    @Cacheable(cacheNames = "ObjRefByPoj", key = "#p0")
    public List<ObjRef> refByPojId(Long id) {
        if (id == null) {
            throw new IllegalArgumentException();
        }
        var query = new LambdaQueryChainWrapper<>(ObjRef.class);
        query.eq(ObjRef::getUnitId, id);
        return objRefMapper.selectList(query);
    }

    @Cacheable(cacheNames = "ObjRefByObj", key = "#p0")
    public List<ObjRef> refByObjId(Long id) {
        if (id == null) {
            throw new IllegalArgumentException();
        }
        var query = new LambdaQueryChainWrapper<>(ObjRef.class);
        query.eq(ObjRef::getUnitId, id);
        return objRefMapper.selectList(query);
    }

    @Transactional
    public void add(ObjRefDto objRefDto) {
        _this.add(ObjRef.fromDto(objRefDto));
    }

    @Transactional
    public void add(ObjRef objRef) {
        objRef.setObjId(null);
        if (StrUtil.isBlankIfStr(objRef.getUnitId()) || StrUtil.isBlankIfStr(objRef.getObjId())) {
            throw new IllegalArgumentException();
        }
        List<ObjRef> objRefs = _this.refByPojId(objRef.getUnitId());
        for (ObjRef r : objRefs) {
            if (r.getObjId().equals(objRef.getObjId())) {
                throw new MessageException("重复引用");
            }
        }
        objRef.setId(redisIdWorker.nextId());
        objRefMapper.insert(objRef);
    }

    @Transactional
    public void deleteById(String id) {
        if (StrUtil.isBlankIfStr(id) || NumberUtil.isLong(id)) {
            throw new IllegalArgumentException();
        }
        Long _id = Long.parseLong(id);
        ObjRef objRef = objRefMapper.selectById(_id);
        if (objRef == null) {
            throw new MessageException("引用不存在");
        }
        _this.delete(objRef);
    }

    @Transactional
    public void delete(ObjRefDto objRefDto) {
        _this.delete(ObjRef.fromDto(objRefDto));
    }

    @Caching(evict = {
            @CacheEvict(cacheNames = "ObjReByObj", key="#p0.objId"),
            @CacheEvict(cacheNames = "ObjReByPoj", key="#p0.unitId")
    })
    @Transactional
    public void delete(ObjRef objRef) {
        objRefMapper.deleteById(objRef);
    }

    @CacheEvict(cacheNames = "ObjReByPoj", key="#p0")
    @Transactional
    public void deleteByPojId(Long id) {
        var query = new LambdaQueryChainWrapper<>(ObjRef.class);
        query.eq(ObjRef::getUnitId, id);
        objRefMapper.delete(query);
    }
}
